﻿using Iit.Automation.Browsers.Shared;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Iit.Automation.Browsers
{
    public class ComponentFactory : IComponentFactory
    {
        private IitEnums.Environment _environment;
        private IitEnums.RegisteredBrowsers _whichBrowser;
        private IitEnums.PlatFormTypes _platform;
        private IBrowser _browser;

        private static Dictionary<Type, IConfigurableComponent> ComponentInstances;
        private static Dictionary<IitEnums.Environment, ComponentFactory> SelfInstances;
        private static Dictionary<Type, Dictionary<IitEnums.Environment, Type>> TypeLibrary;

        public IBrowser Browser
        {
            get
            {
                return _browser;
            }
        }

        public static ComponentFactory GetInstance(IBrowser browser, IitEnums.RegisteredBrowsers whichBrowser, IitEnums.PlatFormTypes platFormType)
        {
            IitEnums.Environment env = GetEnvironment(whichBrowser, platFormType);
            if (!SelfInstances.ContainsKey(env))
            {
                SelfInstances.Add(env, new ComponentFactory(whichBrowser, platFormType));
            }

            SelfInstances[env]._browser = browser;
            return SelfInstances[env];
        }

        private ComponentFactory(IitEnums.RegisteredBrowsers whichBrowser = IitEnums.RegisteredBrowsers.Chrome, IitEnums.PlatFormTypes platFormType = IitEnums.PlatFormTypes.Desktop)
        {
            this._environment = GetEnvironment(whichBrowser, platFormType);
            this._whichBrowser = whichBrowser;
            this._platform = platFormType;
        }

        public static void Initialize(Dictionary<Type, Dictionary<IitEnums.Environment, Type>> typeLibrary)
        {
            TypeLibrary = typeLibrary;
            SelfInstances = new Dictionary<IitEnums.Environment, ComponentFactory>();
            ComponentInstances = new Dictionary<Type, IConfigurableComponent>();
        }

        public IConfigurableComponent GetComponent<T>(bool forceNew = false, bool keepUniqueInstance = true)
        {
            IConfigurableComponent component = (IConfigurableComponent)((!ComponentInstances.ContainsKey(typeof(T)) || (forceNew && ComponentInstances.ContainsKey(typeof(T)))) ? GetComponentInstance(typeof(T)) : ComponentInstances[typeof(T)]);
            component.ConfigureMe(_browser, this._environment);
            return component;
        }

        private IConfigurableComponent GetComponentInstance(Type type)
        {
            if (!TypeLibrary.ContainsKey(type))
                throw new Exception(string.Format("{0}: is not registered!", type.Name));

            if (!TypeLibrary[type].ContainsKey(_environment))
                throw new Exception(string.Format("Type: {0}, either doesn't support {1} or is not registered on platform.", type.Name, _environment.ToString()));

            IConfigurableComponent component = (IConfigurableComponent)Activator.CreateInstance(TypeLibrary[type][_environment]);
            ComponentInstances.Add(type, component);
            return component;
        }

        private static IitEnums.Environment GetEnvironment(IitEnums.RegisteredBrowsers browser, IitEnums.PlatFormTypes platFormType)
        {
            if (browser == IitEnums.RegisteredBrowsers.Chrome && platFormType == IitEnums.PlatFormTypes.Desktop)
                return IitEnums.Environment.DesktopChrome;
            else if (browser == IitEnums.RegisteredBrowsers.Chrome && platFormType == IitEnums.PlatFormTypes.SmartPhone)
                return IitEnums.Environment.SmartPhoneChrome;
            else if (browser == IitEnums.RegisteredBrowsers.FireFox && platFormType == IitEnums.PlatFormTypes.Desktop)
                return IitEnums.Environment.DesktopFireFox;
            else if (browser == IitEnums.RegisteredBrowsers.IE && platFormType == IitEnums.PlatFormTypes.Desktop)
                return IitEnums.Environment.DesktopIE;
            else if (browser == IitEnums.RegisteredBrowsers.Safari && platFormType == IitEnums.PlatFormTypes.Desktop)
                return IitEnums.Environment.DesktopSafari;
            else if (browser == IitEnums.RegisteredBrowsers.Safari && platFormType == IitEnums.PlatFormTypes.SmartPhone)
                return IitEnums.Environment.SmartPhoneSafari;

            return IitEnums.Environment.DesktopChrome;
        }
    }
}
